﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="CsvContentIdProxyConverter.cs" company="CodePlex">
//   The MIT License
//   Copyright (c) 2013 Julien Blin
//   
//   Permission is hereby granted, free of charge, to any person obtaining a copy
//   of this software and associated documentation files (the "Software"), to deal
//   in the Software without restriction, including without limitation the rights
//   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//   copies of the Software, and to permit persons to whom the Software is
//   furnished to do so, subject to the following conditions:
//   
//   The above copyright notice and this permission notice shall be included in
//   all copies or substantial portions of the Software.
//   
//   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//   THE SOFTWARE.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------

namespace UCodeFirst.Converters
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;

    using Umbraco.Core;

    /// <summary>
    /// A <see cref="IConverter"/> that parses CSV node id values and loads appropriate content.
    /// Returns an <see cref="IEnumerable"/>
    /// </summary>
    public class CsvContentIdProxyConverter : IConverter
    {
        /// <summary>
        /// Read the value from Umbraco (<paramref name="value"/>) and converts it for the target property.
        /// </summary>
        /// <param name="propertyInfo">
        ///     The target property info.
        /// </param>
        /// <param name="value">
        ///     The value from Umbraco.
        /// </param>
        /// <returns>
        /// The converted value.
        /// </returns>
        public object Read(PropertyInfo propertyInfo, string value)
        {
            var targetPropertyTypeElement = propertyInfo.PropertyType.GetGenericEnumerableType();
            if (targetPropertyTypeElement == null)
            {
                throw new UCodeFirstException(Resources.UnableToDetermineTheUnderlyingTypeOfCollection.InvariantFormat(propertyInfo.PropertyType));
            }

            var result = new List<object>();

            if (!string.IsNullOrEmpty(value))
            {
                var nodeIds = value.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries)
                                   .Select(x =>
                                       {
                                           int parsed;
                                           if (int.TryParse(x.Trim(), out parsed))
                                           {
                                               return parsed;
                                           }

                                           return int.MinValue;
                                       });
                result = nodeIds.Where(x => x != int.MinValue).Select(x => new ContentTypeRealProxy(targetPropertyTypeElement, x).GetTransparentProxy()).ToList();
            }

            if (propertyInfo.PropertyType.IsArray)
            {
                var typedResult = Array.CreateInstance(targetPropertyTypeElement, result.Count());
                for (var i = 0; i < typedResult.Length; i++)
                {
                    typedResult.SetValue(result[i], i);
                }

                return typedResult;
            }
            else
            {
                var typedResult = typeof(List<>).MakeGenericType(targetPropertyTypeElement).CreateInstance<IList>();
                foreach (var contentTypeBase in result)
                {
                    typedResult.Add(contentTypeBase);
                }

                return typedResult;
            }
        }
    }
}
